from toscawidgets.api import Widget, WidgetRepeater, RepeatedWidget, \
                             default_rule, adapt_value, CSSLink
from toscawidgets.decorator import decorate
from toscawidgets.widgets.forms.fields import name2label, TableMixin, \
                                              Form, FormFieldRepeater, \
                                              ContainerMixin, FormField
from formencode.schema import Schema

__all__ = ["Grid", "EditableGrid"]

grid_css = CSSLink(
    modname=__name__,
    filename='static/grid.css',
    )

class Cell(Widget):
    template = """<span id="${id}" class="${css_class}">${value}</span>"""

class Row(RepeatedWidget):
    template = """\
<tr xmlns="http://www.w3.org/1999/xhtml" 
    xmlns:py="http://genshi.edgewall.org/"
    class="${'row_%d'%repetition} ${('even','odd')[repetition%2]}">
    <td py:for="col_num, col in enumerate(children)" 
        class = "${'col_%d'%col_num}"
        py:content="display_child(col, row=row)" />
</tr>"""
    engine_name = "genshi"

    def prepare_dict(self, value, d, adapt=True):
        d['row'] = value
        return super(Row, self).prepare_dict(value, d, adapt)

class Grid(Widget, TableMixin):
    template = "genshi:toscawidgets.widgets.grids.templates.grid"
    css = [grid_css]
    css_classes = ["grid"]
    params = ["max_rows", "columns", "error"]
    columns = []
    max_rows = 20

    cell_factory = Cell
    repeater_factory = WidgetRepeater
    row_factory = Row
    

    def __init__(self, id=None, parent=None, children=[], **kw):
        super(Grid, self).__init__(id, parent, children, **kw)
        self._widgets, self._labels = self._parse_columns(self.columns)
        row = self.row_factory('row', children=self._widgets)
        self.repeater_factory('row', self, widget=row,
                              repetitions=0, max_repetitions=self.max_rows)

    def _parse_columns(self, columns):
        labels = []
        widgets = []
        for i, column in enumerate(columns):
            # first normalize to 2n tuple
            if isinstance(column, str):
                column = (name2label(column), column)
            elif isinstance(column, Widget):
                column = (getattr(column, 'label_text', name2label(column.id)),
                          column)

            # create cell-displaying widgets 
            label, column = column
            if isinstance(column, str):
                widget = self.cell_factory(column, repetition=i)
            elif isinstance(column, Widget):
                if column.id is None:
                    raise ValueError(
                        "A widget for displaying columns must have an id")
                widget = column.clone(repetition=i)
            else:
                raise TypeError("Unknown type for column: %s" % type(column))

            widgets.append(widget)
            labels.append(label)
        return widgets, labels

    [adapt_value.when("isinstance(value, list)")]
    def __adapt_value(self, value):
        return dict(row=value)

    [adapt_value.when("value is None")]
    def __adapt_value_graceful_fallback(self, value):
        # Return an empty list so we don't brek with a missing value
        return dict()

    def update_params(self, d):
        Widget.update_params(self,d)
        d.labels = self._labels






class EditableRow(ContainerMixin, FormField, Row):
    template = """\
<tr xmlns="http://www.w3.org/1999/xhtml" 
    xmlns:py="http://genshi.edgewall.org/"
    class="${'row_%d'%repetition}">
    <td py:for="col_num, col in enumerate(children)" 
        class = "${'col_%d'%col_num}"
        py:content="display_child(col, row=row)" />
    <td py:if="error" class="fielderror"  py:content="error" />
</tr>"""

class GridSchema(Schema):
    def _to_python(self, value, state=None):
        return Schema._to_python(self, value, state)['row']

class EditableGrid(FormField, Grid):
    repeater_factory = FormFieldRepeater
    row_factory = EditableRow
    validator = GridSchema

